package EA.operators.selection;
import EA.*;
import RKUjava.util.RKUValuation;
import RKUjava.lang.RKUCloneable;

/** This class implements a random selection. This can be used to select
    parents in crossover etc.<br>
    <b>Note:</b> If you want to clone the objects you must
    implement the interface RKUCloneable.
    @see RKUjava.lang.RKUCloneable
*/
public class RandomSelection extends Selection
{
  
  /** Perform a random selection among the sources. <br>
      <b>Note:</b> Objects are NOT cloned.
      @param sources The object to select between. 
      @param numberofselected The size of the resulting array.
  */
  public static Object[] select(Object[] sources, int numberofselected)
  {
    return selectInto(sources, numberofselected, true, false, 0, sources.length, new Object[numberofselected]);
  }

  /** Perform a random selection among the sources. <br>
      <b>Note:</b> Objects are NOT cloned.
      @param sources The object to select between. 
      @param numberofselected The size of the resulting array.
      @param maximization Boolean indicating whether this is a maximization or
      minimization selection. This has no effect when selecting at random.
  */
  public static Object[] select(Object[] sources, int numberofselected, boolean maximization)
  {
    return selectInto(sources, numberofselected, maximization, false, 0, sources.length, new Object[numberofselected]);
  }

  /** Perform a random selection among the sources. <br>
      @param sources The object to select between. 
      @param numberofselected The size of the resulting array.
      @param maximization Boolean indicating whether this is a maximization or
      minimization selection. This has no effect when selecting at random.
      @param cloneobjects Boolean indicating whether you want to clone the 
      selected object. (Remember to implement cloneable)
  */
  public static Object[] select(Object[] sources, int numberofselected, boolean maximization, boolean cloneobjects)
  {
    return selectInto(sources, numberofselected, maximization, cloneobjects, 0, sources.length, new Object[numberofselected]);
  }

  /** Perform a random selection among the sources in the chosen range. <br>
      <b>Note:</b> The source objects must implement the interface RKUValuation
      from the package RKUjava.util. Passing 0 in <tt>lowerindex</tt> and 
      sources.length in <tt>upperindex</tt> will perform a selection among all
      objects in the sources-array.
      @param sources The object to select between. 
      @param numberofselected The size of the resulting array.
      @param maximization Boolean indicating whether this is a maximization or
      minimization selection.
      @param cloneobjects Boolean indicating whether you want to clone the 
      selected object. (Remember to implement cloneable)
      @param lowerindex The lower index of the range.
      @param upperindex The upper index of the range + 1. 
  */
  public static Object[] select(Object[] sources, int numberofselected, boolean maximization, boolean cloneobjects, int lowerindex, int upperindex) 
  {
    return selectInto(sources, numberofselected, maximization, cloneobjects, lowerindex, upperindex, new Object[numberofselected]);
  }

  /** Perform a random selection among the sources and place the selected in an array. <br>
      <b>Note:</b> The source objects must implement the interface RKUValuation
      from the package RKUjava.util. When using this method the object with
      highest value is selected. Objects are NOT cloned.
      @param sources The object to select between. 
      @param numberofselected The size of the resulting array.
      @param destination The array to place the selected in. MUST be big 
      enough to hold all entries
  */
  public static Object[] selectInto(Object[] sources, int numberofselected, Object[] destination)
    {
    return selectInto(sources, numberofselected, true, false, 0, sources.length, destination);
    };

  /** Perform a random selection among the sources and place the selected in an array. <br>
      <b>Note:</b> The source objects must implement the interface RKUValuation
      from the package RKUjava.util. Objects are NOT cloned.
      @param sources The object to select between. 
      @param numberofselected The size of the resulting array.
      @param maximization Boolean indicating whether this is a maximization or
      minimization selection.
      @param destination The array to place the selected in. MUST be big 
      enough to hold all entries
  */
  public static Object[] selectInto(Object[] sources, int numberofselected, boolean maximization, Object[] destination) 
    {
    return selectInto(sources, numberofselected, maximization, false, 0, sources.length, destination);
    };

  /** Perform a random selection among the sources and place the selected in an array. <br>
      <b>Note:</b> The source objects must implement the interface RKUValuation
      from the package RKUjava.util. 
      @param sources The object to select between. 
      @param numberofselected The size of the resulting array.
      @param maximization Boolean indicating whether this is a maximization or
      minimization selection.
      @param cloneobjects Boolean indicating whether you want to clone the 
      selected object. (Remember to implement cloneable)
      @param destination The array to place the selected in. MUST be big 
      enough to hold all entries
  */
  public static Object[] selectInto(Object[] sources, int numberofselected, boolean maximization, boolean cloneobjects, Object[] destination) 
    {
    return selectInto(sources, numberofselected, maximization, cloneobjects, 0, sources.length, destination);
    };

  /** Perform a random selection among the sources in the chosen range and place the selected in an array. <br>
      <b>Note:</b> The source objects must implement the interface RKUValuation
      from the package RKUjava.util. Passing 0 in <tt>lowerindex</tt> and 
      sources.length in <tt>upperindex</tt> will perform a selection among all
      objects in the sources-array.
      @param sources The object to select between. 
      @param numberofselected The size of the resulting array.
      @param maximization Boolean indicating whether this is a maximization or
      minimization selection.
      @param cloneobjects Boolean indicating whether you want to clone the 
      selected object. (Remember to implement cloneable)
      @param lowerindex The lower index of the range.
      @param upperindex The upper index of the range + 1. 
      @param destination The array to place the selected in. MUST be big 
      enough to hold all entries
  */
  public static Object[] selectInto(Object[] sources, int numberofselected, boolean maximization, boolean cloneobjects, int lowerindex, int upperindex, Object[] destination)
    {
	int i, index1, candidates;
	
	candidates = upperindex-lowerindex;
	
	if (cloneobjects==false) {
	    for (i=0;i<numberofselected;i++) {
		index1 = lowerindex+UsefulRoutines.randomInt(candidates);
		destination[i] = sources[index1];
	    }
	}
	else {
	    for (i=0;i<numberofselected;i++) {
		index1 = lowerindex+UsefulRoutines.randomInt(candidates);
		destination[i] = ((RKUCloneable)sources[index1]).clone();
	    }
	}
	return destination;
    };


}
